package pub.tbc.hh.payment.service.weixin;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import pub.tbc.hh.payment.domain.WeixinUnifiedorderRequest;
import pub.tbc.toolkit.core.EmptyUtil;
import pub.tbc.toolkit.core.encode.MD5;

import java.net.URLEncoder;
import java.util.*;

/**
 * @auth tbc on 2018/5/11.
 */
@Component
public class WeixinPaymentUtil {
    @Autowired
    private Environment environment;

    private String appId() {
        return EmptyUtil.requireNonNull(environment.getProperty("payment.weixin.appid"), "找不到可用公众账号ID");
    }

    private String mchId() {
        return EmptyUtil.requireNonNull(environment.getProperty("payment.weixin.mch_id"), "找不到可用商户号");
    }

    // key为商户平台设置的密钥key
    private String key() {
        return EmptyUtil.requireNonNull(environment.getProperty("payment.weixin.key"), "找不到密钥key");
    }

    public WeixinUnifiedorderRequest collocate(WeixinUnifiedorderRequest request) {
        request.setAppid(appId());
        request.setMchId(mchId());
        return request;
    }

    public String sign(Map<String, String> map) {
        TreeMap<String, String> treeMap = new TreeMap<>(Comparator.naturalOrder());
        treeMap.putAll(map);
        StringBuilder builder = new StringBuilder();
        treeMap.forEach((k, v) -> builder.append(k).append("=").append(v).append("&"));
        String str = builder.append("key=").append(key()).toString();
        return MD5.getMD5(str).toUpperCase();
    }

    public String toXml(WeixinUnifiedorderRequest request) {
        StringBuilder sb = new StringBuilder("<xml>");
        Map<String, String> map = request.toMap();
        map.forEach((k, v) -> sb.append("<").append(k).append(">").append("<![CDATA[").append(v).append("]]").append("</").append(k).append(">"));
        sb.append("<sign>").append(sign(map)).append("</sign>");
        sb.append("</xml>");
        return sb.toString();
    }


    /**
     * 方法用途: 对所有传入参数按照字段名的Unicode码从小到大排序（字典序），并且生成url参数串<br>
     * 实现步骤: <br>
     *
     * @param paraMap    要排序的Map对象
     * @param urlEncode  是否需要URLENCODE
     * @param keyToLower 是否需要将Key转换为全小写
     *                   true:key转化成小写，false:不转化
     * @return
     */
    public static String formatUrlMap(Map<String, String> paraMap, boolean urlEncode, boolean keyToLower) {
        String buff;
        Map<String, String> tmpMap = paraMap;
        try {
            List<Map.Entry<String, String>> infoIds = new ArrayList<>(tmpMap.entrySet());
            // 对所有传入参数按照字段名的 ASCII 码从小到大排序（字典序）
            Collections.sort(infoIds, Comparator.comparing(o -> (o.getKey())));
            // 构造URL 键值对的格式
            StringBuilder buf = new StringBuilder();
            for (Map.Entry<String, String> item : infoIds) {
                if (EmptyUtil.isEmpty(item.getKey())) {
                    String key = item.getKey();
                    String val = item.getValue();
                    if (urlEncode) {
                        val = URLEncoder.encode(val, "utf-8");
                    }
                    if (keyToLower) {
                        buf.append(key.toLowerCase() + "=" + val);
                    } else {
                        buf.append(key + "=" + val);
                    }
                    buf.append("&");
                }

            }
            buff = buf.toString();
            if (buff.isEmpty() == false) {
                buff = buff.substring(0, buff.length() - 1);
            }
        } catch (Exception e) {
            return null;
        }
        return buff;
    }

}
